<!doctype html>
<meta charset="utf-8">
<title>Health meter</title>

<canvas width="550" height="400" style="border: 1px dashed black"></canvas>

<script src="requestAnimationFramePolyfill.js"></script>
<script>

//--- The sprite object

var spriteObject =
{
  sourceX: 0,
  sourceY: 0,
  sourceWidth: 64,
  sourceHeight: 64,
  width: 64,
  height: 64,
  x: 0,
  y: 0,
  vx: 0,
  vy: 0,
  
  //Getters
  centerX: function()
  {
    return this.x + (this.width / 2);
  },
  centerY: function()
  {
    return this.y + (this.height / 2);
  },
  halfWidth: function()
  {
    return this.width / 2;
  },
  halfHeight: function()
  {
    return this.height / 2;
  }
};

//--- The main program

//The canvas and its drawing surface
var canvas = document.querySelector("canvas");
var drawingSurface = canvas.getContext("2d");

//Canvas text properties
drawingSurface.font = "normal bold 18px Helvetica";
drawingSurface.fillStyle = "#000";
drawingSurface.textBaseline = "top";

//A variable to display game over message
var message = "";

//An array to store the sprites
var sprites = [];

//Create the monster object 
var monster = Object.create(spriteObject);
monster.sourceX = 64;
monster.x = 350;
monster.y = 100;
sprites.push(monster);

//Create the cat
var cat = Object.create(spriteObject);
cat.x = 150;
cat.y = 250;
sprites.push(cat);

//Create the inner meter and center
//it above the monster
var innerMeter = Object.create(spriteObject);
innerMeter.sourceY = 142;
innerMeter.sourceWidth = 128;
innerMeter.sourceHeight = 14;
innerMeter.width = 128;
innerMeter.height = 14;
innerMeter.x = monster.x - 32;
innerMeter.y = monster.y - 32;
sprites.push(innerMeter);

//Create the outer meter and position it
//over the inner meter
var outerMeter = Object.create(spriteObject);
outerMeter.sourceY = 128;
outerMeter.sourceWidth = 128;
outerMeter.sourceHeight = 14;
outerMeter.width = 128;
outerMeter.height = 14;
outerMeter.x = innerMeter.x;
outerMeter.y = innerMeter.y;
sprites.push(outerMeter);

//Load the image
var image = new Image();
image.addEventListener("load", loadHandler, false);
image.src = "collisionTileSheet.png";

//Arrow key codes
var UP = 38;
var DOWN = 40;
var RIGHT = 39;
var LEFT = 37;

//Directions
var moveUp = false;
var moveDown = false;
var moveRight = false;
var moveLeft = false;

//Add keyboard listeners
window.addEventListener("keydown", function(event)
{
  switch(event.keyCode)
  {
    case UP:
	    moveUp = true;
	    break;
	  
	  case DOWN:
	    moveDown = true;
	    break;
	    
	  case LEFT:
	    moveLeft = true;
	    break;  
	    
	  case RIGHT:
	    moveRight = true;
	    break; 
  }
}, false);

window.addEventListener("keyup", function(event)
{
  switch(event.keyCode)
  {
    case UP:
	    moveUp = false;
	    break;
	  
	  case DOWN:
	    moveDown = false;
	    break;
	    
	  case LEFT:
	    moveLeft = false;
	    break;  
	    
	  case RIGHT:
	    moveRight = false;
	    break; 
  }
}, false);

function loadHandler()
{ 
  update();
}

function update()
{
   //The animation loop
   requestAnimationFrame(update, canvas);

   //Up
   if(moveUp && !moveDown)
   {
     cat.vy = -5;
   }
   //Down
   if(moveDown && !moveUp)
   {
     cat.vy = 5;
   }
   //Left
   if(moveLeft && !moveRight)
   {
     cat.vx = -5;
   }
   //Right
   if(moveRight && !moveLeft)
   {
     cat.vx = 5;
   }

   //Set the cat's velocity to zero if none of the keys are being pressed
   if(!moveUp && !moveDown)
   {
     cat.vy = 0;
   }
   if(!moveLeft && !moveRight)
   {
     cat.vx = 0;
   }

   //Move the cat 
   cat.x += cat.vx;
   cat.y += cat.vy;
  
  //Check for a collision between the cat and the monster
  //and change the monster's state if they touch
  if(hitTestRectangle(cat, monster))
  {
    if(innerMeter.width > 0)
    {
      innerMeter.width--;
      innerMeter.sourceWidth--;
    }
  }
  if(innerMeter.width < 1)
  {
    message = "Game Over!";
  }
    
  //Render the sprites  
  render();
}

function hitTestRectangle(r1, r2)
{
  //A variable to determine whether there's a collision
  var hit = false;
  
  //Calculate the distance vector
  var vx = r1.centerX() - r2.centerX();
  var vy = r1.centerY() - r2.centerY();
  
  //Figure out the combined half-widths and half-heights
  var combinedHalfWidths = r1.halfWidth() + r2.halfWidth();
  var combinedHalfHeights = r1.halfHeight() + r2.halfHeight();
  
  //Check for a collision on the x axis
  if(Math.abs(vx) < combinedHalfWidths)
  {
    //A collision might be occuring.
    //Check for a collision on the y axis
    if(Math.abs(vy) < combinedHalfHeights)
    {
      //There's definitely a collision happening
      hit = true;
    }
    else
    {
      //There's no collision on the y axis
      hit = false;
    }   
  }
  else
  {
    //There's no collision on the x axis
    hit = false;
  }
  
  return hit;
}

function render(event)
{ 
  drawingSurface.clearRect(0, 0, canvas.width, canvas.height);
  
  if(sprites.length !== 0)
  {
    for(var i = 0; i < sprites.length; i++)
    {
      var sprite = sprites[i];
      drawingSurface.drawImage
      (
        image, 
        sprite.sourceX, sprite.sourceY, 
        sprite.sourceWidth, sprite.sourceHeight,
        Math.floor(sprite.x), Math.floor(sprite.y), 
        sprite.width, sprite.height
      ); 
    }
  }
  
  //Display the message above the meter
  drawingSurface.fillText(message, outerMeter.x, outerMeter.y - 25);
}

</script>
